package cn.eonshine.cuba.lsms.modular.biz.service.impl;

import java.math.BigDecimal;
import java.util.Calendar;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cglib.beans.BeanCopier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;

import cn.eonshine.cuba.inf.common.util.DateUtils;
import cn.eonshine.base.core.util.LocaleStringUtil;
import cn.eonshine.cuba.inf.common.http.InfStatus;
import cn.eonshine.cuba.inf.modular.biz.entity.CustomerInventoryData;
import cn.eonshine.cuba.lsms.modular.CommonService;
import cn.eonshine.cuba.lsms.modular.basic.entity.CustomerLsms;
import cn.eonshine.cuba.lsms.modular.basic.entity.Office;
import cn.eonshine.cuba.lsms.modular.basic.entity.OilTankInfo;
import cn.eonshine.cuba.lsms.modular.basic.mapper.CustomerLsmsMapper;
import cn.eonshine.cuba.lsms.modular.basic.mapper.OfficeMapper;
import cn.eonshine.cuba.lsms.modular.basic.mapper.OilTankInfoMapper;
import cn.eonshine.cuba.lsms.modular.biz.entity.SRealOildepotStock;
import cn.eonshine.cuba.lsms.modular.biz.entity.SRealOildepotStockDay;
import cn.eonshine.cuba.lsms.modular.biz.mapper.SRealOildepotStockDayMapper;
import cn.eonshine.cuba.lsms.modular.biz.mapper.SRealOildepotStockMapper;
import cn.eonshine.cuba.lsms.modular.biz.service.ICustomerInventoryDataService;
import cn.eonshine.cuba.lsms.modular.biz.service.IInfRealTimeDataOffService;

@Service
public class CustomerInventoryDataServiceImpl extends CommonService<CustomerInventoryData> implements ICustomerInventoryDataService {

	@Autowired
	private SRealOildepotStockMapper realOildepotStockMapper;
	@Autowired
	private SRealOildepotStockDayMapper realOildepotStockDayMapper;
	@Autowired
	private OfficeMapper officeMapper;
	@Autowired
	private CustomerLsmsMapper customerLsmsMapper;
	@Autowired
	private OilTankInfoMapper oilTankInfoMapper;

	@Autowired
	private IInfRealTimeDataOffService infRealTimeDataOffService;
	
//	@Autowired
//	private ISRealOildepotStockService sRealOildepotStockService;
	
//	@Autowired
//	private ISRealOildepotStockDayService sRealOildepotStockDayService;

	private final String listUrl = "/customerInventoryData/list";
	private final String updateUrl = "/customerInventoryData/update";
	
	@Override
	public void requestCustomerInventoryData() {
		requestData(listUrl, updateUrl, InfStatus.INF_LOG_TYPE.CUSTOMER_INVENTORY_NUM);
	}

	@Transactional
	@Override
	protected Object dataHandle(CustomerInventoryData obj) throws Exception {
		boolean isClosed=false;
		if(obj.getRptDate() != null) {
			isClosed = infRealTimeDataOffService.isClosed(obj.getRptDate());
		}else {
			// 没有业务日期的数据，不接收此数据。
//			throw new Exception("");
			return null;
		}
		// 数据关闭，不再接收此数据。
		if(isClosed) {
			String msg = LocaleStringUtil.getMessage("interface.error.beClosed");
			throw new Exception(msg);
		}
		
		
		// Query from customer to depot
		if(StringUtils.isBlank(obj.getDepotKey())) {
			String depotId = convertCustomerToDeopt(obj);
			obj.setDepotKey(depotId);
		}
		// query for deport oil can id;
		OilTankInfo oilTankInfo = queryOilTankInfo(obj.getDepotKey(), obj.getOilKey());
		
		// save data
		QueryWrapper<SRealOildepotStock> entity = new QueryWrapper<SRealOildepotStock>();
//		entity.where("OIL_DEPOT={0} and OILCAN_ID={1} and OIL_ID={2} and DATA_DATE={3} ", inventoryData.getOrgId(), inventoryData.getOilcanId(), inventoryData.getOilId(), inventoryData.getRptDate());
		entity.lambda().eq(SRealOildepotStock::getOilDepot, obj.getDepotKey());
		entity.lambda().eq(SRealOildepotStock::getOilcanId, oilTankInfo.getId());
		entity.lambda().eq(SRealOildepotStock::getOilId, obj.getOilKey());
		entity.lambda().eq(SRealOildepotStock::getDataDate, obj.getRptDate());
		SRealOildepotStock info = realOildepotStockMapper.selectOne(entity);
		boolean isInsert = false;
		if(info == null) {
			info = new SRealOildepotStock();
			isInsert = true;
		}
		
		info.setOilDepot(obj.getDepotKey());
		info.setOilcanId(oilTankInfo.getId());
		info.setOilId(obj.getOilKey());
		info.setQuantity(BigDecimal.valueOf(obj.getQuantity()));
		info.setDataDate(obj.getRptDate());
		if(isInsert) {
			info.setCreateDate(DateUtils.getCubaDate(Calendar.getInstance().getTime()));
		}
		info.setUpdateDate(DateUtils.getCubaDate(Calendar.getInstance().getTime()));
		info.setRemarks(obj.getRemarks());
		info.setEmptyTankQuantity(BigDecimal.valueOf(obj.getEmptyTankQuantity()));
		info.setThirdPartyQuantity(BigDecimal.valueOf(0));
		
		if(isInsert) {
			realOildepotStockMapper.insert(info);
		}else {
			realOildepotStockMapper.updateById(info);
		}
		
		handleTrancDay(info);
		
		return info;
	}

	@Override
	protected List<CustomerInventoryData> feadBackDataHandle(Object obj, CustomerInventoryData t,
			List<CustomerInventoryData> feadBackDataLists) throws Exception {
		
		CustomerInventoryData tmpBack = new CustomerInventoryData();
		tmpBack.setLsmsUpdate(InfStatus.LSMS_UPDATE_EXTRACT_YES);
		feadBackDataLists.add(tmpBack);
		return feadBackDataLists;
	}

	/**
	 * 
	 * @Title: convertCustomerToDeopt   
	 * @Description: 通过接口数据，查询油库对象
	 * by Alan 2019-06-21 15:30:19
	 * @param obj
	 * @return
	 * @throws Exception      
	 * @return  String
	 */
	private String convertCustomerToDeopt(CustomerInventoryData obj) throws Exception {
		QueryWrapper<CustomerLsms> custQuery = new QueryWrapper<CustomerLsms>();
		custQuery.lambda().eq(CustomerLsms::getCode, obj.getCustomerId());
		CustomerLsms customerLsms=null;
		try {
			customerLsms = customerLsmsMapper.selectOne(custQuery);
		} catch (Exception e) {
			throw new Exception("Match multiple customers in LSMS: "+obj);
		}
		if(customerLsms == null) {
			throw new Exception("no this customer: "+obj);
		}
		QueryWrapper<Office> officeQuery = new QueryWrapper<Office>();
		officeQuery.lambda().eq(Office::getSubDepotCode, customerLsms.getId());
		Office depot=null;
		try {
			depot = officeMapper.selectOne(officeQuery);
		} catch (Exception e) {
			throw new Exception("Multiple depot belongs to customer Match in LSMS: "+obj);
		}
		if(depot == null) {
			throw new Exception("this customer have no depot: "+obj);
		}
		return depot.getId();
	}
	
	/**
	 * 
	 * @Title: queryOilTankInfo   
	 * @Description: 通过油库和油品，查询客户唯一的油罐，如果有多个油罐，抛出异常。 
	 * by Alan 2019-06-21 15:31:58
	 * @param oilDepotId
	 * @param oilId
	 * @return      
	 * @return  OilTankInfo
	 */
	private OilTankInfo queryOilTankInfo(String oilDepotId, String oilId) throws Exception {
		QueryWrapper<OilTankInfo> tankOilQuery = new QueryWrapper<OilTankInfo>();
		tankOilQuery.lambda().eq(OilTankInfo::getOilDepotId, oilDepotId)
			.eq(OilTankInfo::getOilId, oilId);
		OilTankInfo info = null;
		try {
			info = oilTankInfoMapper.selectOne(tankOilQuery);
			if(info == null) {
				throw new Exception("query no depot tank info in LSMS");
			}
		} catch (Exception e) {
			e.printStackTrace();
			throw new Exception("query to many depot tank info in LSMS");
		}
		return info;
	}

	/**
	 * 
	 * @Title: handleTrancDay   
	 * @Description: Report Of Real Oil Depot  
	 * by Alan 2019-04-10 10:58:49
	 * @param info      
	 * @return  void
	 */
	private void handleTrancDay(SRealOildepotStock info) {
		final BeanCopier copier = BeanCopier.create(SRealOildepotStock.class, SRealOildepotStockDay.class, false);
		SRealOildepotStockDay day = new SRealOildepotStockDay();
		copier.copy(info, day, null);
		day.setId(null);
		day.setbDate(DateUtils.truncate(info.getDataDate(), Calendar.DATE));
		
		QueryWrapper<SRealOildepotStockDay> entity = new QueryWrapper<SRealOildepotStockDay>();
//		entity.where("b_date={0} and oil_depot={1} and oilcan_id={2} ", day.getbDate(), day.getOilDepot(), day.getOilcanId());
		entity.lambda().eq(SRealOildepotStockDay::getbDate, day.getbDate());
		entity.lambda().eq(SRealOildepotStockDay::getOilDepot, day.getOilDepot());
		entity.lambda().eq(SRealOildepotStockDay::getOilcanId, day.getOilcanId());
		SRealOildepotStockDay dbDay = realOildepotStockDayMapper.selectOne(entity);
		
		if(dbDay != null) {
			copier.copy(day, dbDay, null);
			realOildepotStockDayMapper.updateById(dbDay);
		}else {
			realOildepotStockDayMapper.insert(day);
		}
		
	}
}
